package by.bsu.wp.latextool.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jgrapht.DirectedGraph;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;

import by.bsu.wp.latextool.exception.NFRSProblemInconsistantException;

public class NotFullRankSystemProblem {

	/**
	 * sourceNet describes the source net <b>S</b> as a directed graph
	 */
	private DirectedGraph<Integer, DefaultEdge> sourceNet;

	/**
	 * productFlowNets describes a list of the flow nets <b>S^k</b> in the net
	 * <b>S</b> for every product <b>k</b> from set <b>K</b>, the size of the
	 * list is the cardinality of the set <b>K</b>
	 */
	private Map<Integer, DirectedGraph<Integer, ProductFlowEdge>> productFlowNets;

	/**
	 * numberOfBaseEquations describes number of base equations (<b>q</b>
	 * coefficient value)
	 */
	private int numberOfBaseEquations;

	/**
	 * baseEquationTotals represents <b>alpha_p</b> coefficients for every base
	 * equation <b>p</b>
	 */
	private Map<Integer, Integer> baseEquationTotals;

	/**
	 * zeroEdges map contains edges from <b>U_0</b> set and corresponding
	 * <b>z_i_j</b> value
	 */
	private Map<DefaultEdge, Integer> zeroEdges;

	/**
	 * balances describes values of <b>a</b> coefficients for every product
	 * transporting net and for every it's vertex
	 */
	private Map<Integer, Map<Integer, Integer>> balances;

	/**
	 * products that net transports
	 */
	private Set<Integer> products;
	
	/**
	 * Returns a set of product transported through vertex <code>vertexIndex</code>
	 * @param vertexIndex
	 * @return <i>K(vertexIndex)</i>
	 */
	public Set<Integer> getProductsForVertex(Integer vertexIndex) {
		Set<Integer> vertexProducts = new HashSet<Integer>();
		for (Map.Entry<Integer, DirectedGraph<Integer, ProductFlowEdge>> entry : productFlowNets.entrySet()) {
			if (entry.getValue().containsVertex(vertexIndex)) {
				vertexProducts.add(entry.getKey());
			}
		}
		return vertexProducts;
	}

	/**
	 * Returns a set of product transported through edge <code>(sourceVertex, targetVertex)</code>
	 * @param sourceVertex
	 * @param targetVertex
	 * @return <i>K(sourceVertex, targetVertex)</i>
	 */
	public Set<Integer> getProductsForEdge(Integer sourceVertex, Integer targetVertex) {
		Set<Integer> edgeProducts = new HashSet<Integer>();
		for (Map.Entry<Integer, DirectedGraph<Integer, ProductFlowEdge>> entry : productFlowNets.entrySet()) {
			if (entry.getValue().containsEdge(sourceVertex, targetVertex)) {
				edgeProducts.add(entry.getKey());
			}
		}
		return edgeProducts;
	}
	
	public int getNumberOFProducts() {
		return products.size();
	}

	public DirectedGraph<Integer, DefaultEdge> getSourceNet() {
		return sourceNet;
	}

	public void setSourceNet(DirectedGraph<Integer, DefaultEdge> sourceNet) {
		this.sourceNet = sourceNet;
	}

	public Map<Integer, DirectedGraph<Integer, ProductFlowEdge>> getProductFlowNets() {
		return productFlowNets;
	}

	public void setProductFlowNets(Map<Integer, DirectedGraph<Integer, ProductFlowEdge>> productFlowNets) {
		this.productFlowNets = productFlowNets;
	}

	public int getNumberOfBaseEquations() {
		return numberOfBaseEquations;
	}

	public void setNumberOfBaseEquations(int numberOfBaseEquations) {
		this.numberOfBaseEquations = numberOfBaseEquations;
	}

	public Map<Integer, Integer> getBaseEquationTotals() {
		return baseEquationTotals;
	}

	public void setBaseEquationTotals(Map<Integer, Integer> baseEquationTotals) {
		this.baseEquationTotals = baseEquationTotals;
	}

	public Map<DefaultEdge, Integer> getZeroEdges() {
		return zeroEdges;
	}

	public void setZeroEdges(Map<DefaultEdge, Integer> zeroEdges) {
		this.zeroEdges = zeroEdges;
	}

	public Map<Integer, Map<Integer, Integer>> getBalances() {
		return balances;
	}

	public void setBalances(Map<Integer, Map<Integer, Integer>> balances) {
		this.balances = balances;
	}

	public Set<Integer> getProducts() {
		return products;
	}

	public void setProducts(Set<Integer> products) {
		this.products = products;
	}

}
